package top.linruchang.util;

import lombok.extern.java.Log;
import top.linruchang.bean.FileAndRules;
import top.linruchang.enums.RegexFileTypeEnum;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 作用：
 *
 * @author LinRuChang
 * @version 1.0
 * @date 2020/11/03
 * @since 1.8
 */
@Log
public class FileUtil {

    /**
     * <p>
     * description: 文件名是否符合其中一个正则 - 可以直接使用已经定义好 {@link RegexFileTypeEnum}
     * </p>
     *
     * @param file
     * @param regexs
     * @return boolean
     */
    public static boolean isTypeFile(File file, String... regexs) {
        return RegexUtil.isMatchAnyRegex(file.getPath(), regexs);
    }

    public static boolean isTypeFile(File file, RegexFileTypeEnum... fileTypeEnums) {
        return isTypeFile(file, Arrays.stream(fileTypeEnums).map(RegexFileTypeEnum::getRegex).toArray(String[]::new));
    }

    public static boolean isTypeFile(Path filePath, String... regexs) {
        return isTypeFile(filePath.toFile(), regexs);
    }

    public static boolean isTypeFile(Path filePath, RegexFileTypeEnum... fileTypeEnums) {
        return isTypeFile(filePath.toFile(), fileTypeEnums);
    }


    /**
     * 是否是Java文件
     */
    public static boolean isJavaFile(File file) {
        return !file.isDirectory() && isTypeFile(file, RegexFileTypeEnum.JAVA.getRegex());
    }

    /**
     * 是否是Class文件
     */
    public static boolean isClassFile(File file) {
        return !file.isDirectory() && isTypeFile(file, RegexFileTypeEnum.CLASS.getRegex());
    }

    /**=========================================================================*/

    /**
     * 获取sourceFile文件下所有子目录
     *
     * @param sourceFile
     * @return
     */
    public static List<File> getSubFiles(File sourceFile) {
        List<File> subFiles = new ArrayList<>();
        getSubFiles(sourceFile, subFiles);
        return subFiles;
    }

    /**
     * <p>
     * description: 获取某个sourceFile【目录、文件】下的所有子文件非目录 - 如果sourceFile非目录则files则是该sourceFile
     * </p>
     *
     * @param sourceFile 目录、文件
     * @param subFiles   目录下的所有子文件
     * @return void
     */
    public static void getSubFiles(File sourceFile, List<File> subFiles) {
        if (sourceFile.isDirectory()) {
            Arrays.stream(sourceFile.listFiles()).forEach(subFile -> {
                getSubFiles(subFile, subFiles);
            });
        } else {
            subFiles.add(sourceFile);
        }

    }

    /**=========================================================================*/

    /**
     * <p>
     * description: 将内容填充入文件
     * </p>
     *
     * @param targetFile  需要被填充的文件
     * @param fillContent 内容
     * @param openOption  如果填充 - 参考{@link StandardOpenOption}
     * @return boolean 是否填充成功
     */
    public static boolean fillFile(File targetFile, String fillContent, OpenOption openOption) {
        try {
            if (createFile(targetFile)) {  //生成文件，然后填充内容入文件
                Files.write(targetFile.toPath(), fillContent.getBytes(), openOption);
            }
        } catch (IOException e) {
            log.info("填充失败：" + e.getMessage());
            return false;
        }
        return true;
    }

    public static boolean fillFile(File targetFile, File sourceFile, OpenOption openOption) throws IOException {
        if (sourceFile.isDirectory()) {
            return false;
        } else {
            byte[] bytes = Files.readAllBytes(sourceFile.toPath());
            return fillFile(targetFile, new String(bytes, "utf-8"), openOption);
        }
    }

    /**
     * 直接将内容插入到文件尾部而不是覆盖整个文件
     */
    public static boolean fillFile(File targetFile, String fillContent) {
        return fillFile(targetFile, fillContent, StandardOpenOption.APPEND);
    }

    public static boolean fillFile(File targetFile, File sourceFile) throws IOException {
        return fillFile(targetFile, sourceFile, StandardOpenOption.APPEND);
    }


    public static boolean fillFile(File sourceFile, FileAndRules fileAndRules) throws IOException {
        String sourceContent = readFile(sourceFile);
        if (fileAndRules.sourceIsNedd(sourceFile) && sourceContent != null) {
            String processedContent = fileAndRules.processContent(sourceContent);
            return fillFile(fileAndRules.getTargetFile(), processedContent);
        }
        return false;
    }

    /**=========================================================================*/

    /**
     * <p>
     * description: 创建文件
     * </p>
     *
     * @param targetFile  目标文件
     * @param isDirectory 目标文件是否是目录
     * @return boolean
     */
    public static boolean createFile(File targetFile, Boolean isDirectory) throws IOException {
        if (isDirectory) {
            return targetFile.mkdirs();
        } else {
            if (!targetFile.isAbsolute()) {
                targetFile.getParentFile().mkdirs();
                return targetFile.createNewFile();
            } else {
                return true;
            }
        }
    }

    /**
     * 默认生成文件而不是目录
     */
    public static boolean createFile(File targetFile) throws IOException {
        return createFile(targetFile, false);
    }

    //==========================================

    /**
     * <p>
     * description: 获取整个文件内容
     * </p>
     *
     * @param file
     * @return java.lang.String
     */
    public static String readFile(File file)  {
        if (file.isDirectory()) {
            return null;
        } else {
            try {
                return new String(Files.readAllBytes(file.toPath()), "utf-8");
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
        }
    }

    public static String readFile(String file)  {
        return readFile(new File(file));
    }

}
